package org.libermundi.theorcs.core.tapestry.services.assets;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.apache.tapestry5.internal.services.AssetResourceLocator;
import org.apache.tapestry5.internal.services.AssetResourceLocatorImpl;
import org.apache.tapestry5.internal.services.ResourceDigestManager;
import org.apache.tapestry5.internal.services.ServicesMessages;
import org.apache.tapestry5.ioc.Resource;
import org.apache.tapestry5.services.AssetFactory;
import org.apache.tapestry5.services.AssetSource;
import org.apache.tapestry5.services.Response;

public class OfsResourceLocator implements AssetResourceLocator {
	private final AssetResourceLocator _defaultLocator;
	
	private final AssetFactory _ofsAssetFactory;
	
	private final ResourceDigestManager _digestManager;
	
	private final Response _response;
	
	public OfsResourceLocator(ResourceDigestManager digestManager, Response response, AssetSource assetSource,
			AssetFactory ofsAssetFactory) {
		_defaultLocator = new AssetResourceLocatorImpl(digestManager, response, assetSource);
		_ofsAssetFactory = ofsAssetFactory;
		_digestManager = digestManager;
		_response = response;
	}

	@Override
	public Resource findClasspathResourceForPath(String path) throws IOException {
		Resource r = findOfsResource(path);
		if (r.exists()) {
            return r;
        }		
		return _defaultLocator.findClasspathResourceForPath(path);
	}

	private Resource findOfsResource(String path) throws IOException {
		Resource resource = _ofsAssetFactory.getRootResource().forFile(path);
		
		if (!_digestManager.requiresDigest(resource)) {
            return resource;
		}

        return validateChecksumOfOfsResource(resource);
	}

    /**
     * Validates the checksum encoded into the resource, and returns the true resource (with the checksum
     * portion removed from the file name).
     */
    private Resource validateChecksumOfOfsResource(Resource resource) throws IOException
    {
        String file = resource.getFile();

        // Somehow this code got real ugly, but it's all about preventing NPEs when a resource
        // that should have a digest doesn't.

        boolean valid = false;
        Resource result = resource;

        int lastdotx = file.lastIndexOf('.');

        if (lastdotx > 0) {
            int prevdotx = file.lastIndexOf('.', lastdotx - 1);

            if (prevdotx > 0) {
                String requestDigest = file.substring(prevdotx + 1, lastdotx);

                // Strip the digest out of the file name.

                String realFile = file.substring(0, prevdotx) + file.substring(lastdotx);

                result = resource.forFile(realFile);

                String actualDigest = _digestManager.getDigest(result);

                valid = requestDigest.equals(actualDigest);
            }
        }

        if (valid) {
        	return result;
        }

        _response.sendError(HttpServletResponse.SC_FORBIDDEN, ServicesMessages.wrongAssetDigest(result));

        return result;
    }	
}
